package com.gagakuai.bpm.service.scheduleTask.bpmtask;

import com.gagakuai.bpm.common.constants.BpmMetaConstants;
import com.gagakuai.bpm.dao.mapper.camunda.ActRuTaskMapper;
import com.gagakuai.bpm.dao.mapper.camunda.WorkFlowInstenceMapper;

import com.gagakuai.bpm.domian.entity.camuda.ActRuTask;
import com.gagakuai.bpm.utils.CollectionUtils;
import com.gagakuai.bpm.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/*
 * @program: bpm_server
 * @description:
 * @author: houhong
 * @create: 2022-07-01 10:57
 */
@Slf4j
@Component
public class DelTaskScheduledTask {

    @Autowired
    private WorkFlowInstenceMapper workFlowInstenceMapper;

    @Autowired
    private ActRuTaskMapper actRuTaskMapper;


    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;


    /*
     * @Author houhong
     * @Description //TODO 异步线程池定时删除
     * @Date 3:41 下午 2022/5/9
     */
    @Async(value = "taskThreadPool")
   // @Scheduled(fixedRate = 1000 * 20)
    public void scheduleDeleteInstance() {

        /*
         *  分布式锁删除流程
         */
        RLock deleteFininedTaskLock = redissonClient.getLock("deleteFininedTaskOwner");
        // 尝试加锁，最多等待100秒
        boolean TEY_GET_LOCK_RESULT;
        try {
            TEY_GET_LOCK_RESULT = deleteFininedTaskLock.tryLock(10, TimeUnit.SECONDS);
            log.info("##======获取【定时删除任务拥有者分布式任务】分布式锁: {}=======##", TEY_GET_LOCK_RESULT);
            if (TEY_GET_LOCK_RESULT) {

                Long startTime = System.currentTimeMillis();
                log.info("##================开始处理已经完成的流程任务====================##");
                log.info("##当前线程名:{}##", Thread.currentThread().getName());
                //从redis中获取所有的key
                Set<String> keys = redisTemplate.keys(BpmMetaConstants.TASK_ORIGIN_OWNER + "*");

                List<String> waitTodealList = new ArrayList<>();

                if (CollectionUtils.isEmpty(keys)) {
                    return;
                }
                for (String key : keys) {
                    String ruTaskId = key.split(BpmMetaConstants.REDIS_FILE_KEY_SEPTOR)[1];
                    waitTodealList.add(ruTaskId);
                }
                //过滤掉不存在的流程
                List<ActRuTask> exitRuTaskList = actRuTaskMapper.selectNotExsitByPrimaryKeyBatch(waitTodealList);
                //过滤 -- 求差集
                List<String> notExitKeysList = waitTodealList.stream().filter(
                        b -> exitRuTaskList.stream().map(ActRuTask::getId).noneMatch(id -> Objects.equals(b, id))).collect(Collectors.toList());

                List<String> waitTodel = new ArrayList<>();
                for (String notExitTaskId : notExitKeysList) {

                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append(BpmMetaConstants.TASK_ORIGIN_OWNER)
                            .append(notExitTaskId);
                    waitTodel.add(stringBuilder.toString());
                }


                if (CollectionUtils.isNotEmpty(waitTodel)) {
                    String[] result = new String[waitTodel.size()];
                    waitTodel.toArray(result);
                    redisUtil.del(result);
                }

                Long endTime = System.currentTimeMillis();
                log.info("#总共耗时{}#", endTime - startTime);
            }
        } catch (Exception e) {
            log.error("========获取分布式任务失败,原因如下:{}============", e.getMessage());
        } finally {
            deleteFininedTaskLock.unlock();
        }

    }


}